##!/usr/bin/env python
##-*- coding: utf-8 -*-
"""

*    IdentGeografica.py
*    This script makes reports from ufw firewall log
*    Geography Identity type can be html 
*    Mestrado em Engenharia de Segurança Informática
*    Escola Superior de tecnologia e Gestão de Beja
*    
*    Copyright 2013 Andreia Graça <198912823@alunos.ipbeja.pt>
*    Copyright 2013 Palmira Martins <198913316@alunos.ipbeja.pt>
*    
*    This program is an academic software.
*    Only for academic purposes. Under free GNU Licences.
"""     
import sys #system calls
import re # re.search
import GeoIP #GeoIP
import sqlite3 #database sqlite3
import datetime 
import optparse #arguments/option parse
import pymaps
import os
import socket
import string

##Open GEOIP data files for ipv4
gic = GeoIP.open('./Geo/GeoIPCity.dat', GeoIP.GEOIP_STANDARD)
##Open GEOIP data files for ipv6
giv6 = GeoIP.open('./Geo/GeoIPv6.dat', GeoIP.GEOIP_MEMORY_CACHE)

def openLog(logfile):
    """
    Function openLog(logfile)
    Receive argument log file ant try to open in read mode
    Exception if could not open the file
    """
    try:
        log=open(logfile, 'r')
        return log
    except Exception, e:
        print "[-] " + str(e)
        sys.exit()

def readLog(log):
    """
    Function readLog(log)
    Read log file and save the important fields in a sqlite3 database
    """
    con=createDb()
    con.cursor()
    con.execute("DROP TABLE IF EXISTS GEOIP")
    con.execute("CREATE TABLE GEOIP(Id integer,Time DATA ,IPsrc TEXT,EventSrc TEXT,Device TEXT,Protocol TEXT,TTL TEXT, SRCPort TEXT, DSTPort TEXT,Country TEXT,CountryName TEXT,Lon TEXT,Lat TEXT, CheckBL TEXT)")
    id=1
    
    for line in log.readlines():
        debug = 0
        if not re.search("SRC=192", line) and not re.search("SRC=0", line) and not re.search("SRC=172", line):
            #IP SRC
            lista = line.split("SRC=")
            IP = lista[1].split(' ')[0]
            #DATA
            lineMonth = str(line)
            dataT = lineMonth[:15]
            #INTERFACE
            device = line.split("IN=")
            dInterface = device[1].split(' ')[0]
            if (str(dInterface) ==""):
                device = line.split("OUT=")
                dInterface = device[1].split(' ')[0]
                #EVENT SOURCE
                event = line.split("IN= ")
                eventSrc = event[1].split('=')[0]
            else:
                eventSrc = "IN"

            #PROTO
            proto=line.split("PROTO=")
            protoInf=proto[1].split(' ')[0]

            try:
                if len(IP)<=15:
                    #SOURCE PORT
                    spt=line.split("SPT=")
                    sptPort=spt[1].split(' ')[0]
                    #DESTINATION PORT
                    dpt=line.split("DPT=")
                    dptPort=dpt[1].split(' ')[0]
                    data=gic.record_by_addr(IP)
                    cty = data['country_code']
                    ctyName =data['country_name']
                    longitude = data['longitude']
                    latitude = data['latitude']
                    ttlinf=line.split("TTL=")
                    ttlData=str(ttlinf[1].split(' ')[0])
                else:
                    cty=giv6.country_code_by_addr_v6(IP)
                    
                con.execute("INSERT INTO GEOIP VALUES (:Id,:Time,:IPsrc,:EventSrc,:Device,:Protocol,:TTL,:SRCPort,:DSTPort,:Country,:CountryName,:Lon,:Lat,:CheckBL)", {"Id":id,"Time":dataT,"IPsrc":IP,"EventSrc":eventSrc,"Device":dInterface,"Protocol":protoInf,"TTL":ttlData,"SRCPort":sptPort,"DSTPort":dptPort,"Country":cty,"CountryName":ctyName,"Lon":longitude,"Lat":latitude,"CheckBL":""})
                id+=1

            except:
                continue            
    con.commit()

    if con:
        con.close()

def createDb():
    """
    Function createDb()
    Creates a sqlite database in directory "./db/" with "ldp.db" name
    Exception lite.Error if cannot create the database
    """
    try:
        con = sqlite3.connect('./db/lpd.db')
        cur = con.cursor()
        return con
    except lite.Error, e:
        print "Error %s:" % e.args[0]
        sys.exit(1)

  
def showmap():
    """
    Function showmap() - Create a google map report with ip geo localization
    """
    now = datetime.datetime.now() #datetime for filename
    mapFileName="Mapa_Ips.htm" 
    con = sqlite3.connect('./db/lpd.db') #connection to database
    cur = con.cursor() # connection cursor
    cur.execute("SELECT Distinct IPsrc, Lon, Lat, CountryName, CheckBL FROM GEOIP Group BY Lon")
    data=cur.fetchall()

    # Create a map - pymaps allows multiple maps in an object
    tmap = pymaps.Map()
    tmap.zoom = 1

    # Add the point to the map
    icon = pymaps.Icon()

    point=[]
    
    for ip, lon, lat, cn, cbl in data:
        # Latitude and longitude
        # Inserts html into the hover effect
        
        cur.execute("SELECT DISTINCT IPsrc FROM GEOIP WHERE Lon=(:Lon)",{"Lon":lon})
        allip=cur.fetchall()
        if len(allip)>1:
            pointhtml="IP Numbers:</br>"
            for x in allip:
                cur.execute("SELECT CountryName, CheckBL FROM GEOIP WHERE IPsrc=(:IPsrc) GROUP BY CountryName",{"IPsrc":x[0]})
                coutryBlacklist=cur.fetchall()
                cn,cbl = coutryBlacklist[0]
                if cbl==" ":
                    pointhtml+=x[0]+" - "+cn+" - <font color=red>"+cbl+"</font></br>"
                else:
                    pointhtml+=x[0]+" - "+cn+" - <font color=green>"+cbl+"</font></br>"
        else:
            if cbl==" ":
                pointhtml= "<p>IP = " + ip + "</br>Country: " + cn + "</br><font color=red>" + cbl +"</font></p>"
            else:
                pointhtml= "<p>IP = " + ip + "</br>Country: " + cn + "</br><font color=green>" + cbl +"</font></p>"
        x=[lat, lon, pointhtml, icon.id]
        point.append(x)
    
    tmap.setpoint(point)
    tmap.center = (1.757537,144.492188)

    # Google key maps api
    GOOGLE_KEY = "AIzaSyBxyOnH1iUlwuftyIkHmoGxBsxriqiVPuo"
    gmap = pymaps.PyMap(key=GOOGLE_KEY, maplist=[tmap])
    gmap.addicon(icon)

    # create file map
    file = open(mapFileName, "w")

    mapcode = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Mapa de Ips - MESI </title>"""
    # pymapjs exports all the javascript required to build the map!
    mapcode += gmap.pymapjs()
    mapcode +=""" </head>
<body onload="load()" onunload="GUnload()">
<h1> Mapas de Localização de IP</h1>
<div id="map" style="width: 1000px; height: 600px"></div>
</body>
</html>"""

    file.write(mapcode)
    file.close()
    if con:
        con.close()
    print "Done!\nGoogle Map created with filename "+ mapFileName
    return mapFileName



  


def main():
    """
    main funtion
    first openLog file function and readLog function
    call function, showmap() if this the type of argument is given
    arguments obtained with optparse
    """
    parser = optparse.OptionParser(usage="Usage: %prog " +"-f <log file> -m", version='%prog 0.01 - MESI2013')
    parser.add_option("-f", dest="file", type="string", help="name of the log file")
  
    parser.add_option("-m", "--map", action="store_true", dest="map", help="create a Google Map report in html file")
    (options, args) = parser.parse_args()

    if options.file:
        print "... (please wait)"
        savelog=openLog(options.file)
        readLog(savelog)
    else:
        print "You must specify a log file."
        print ("Usage: -h for help")
        exit(0)

   
   
    if options.map == True:
        file=showmap()
        command = "firefox " + str(file)
        os.system(command)

if __name__ == '__main__':
    main()
